home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_100 / 121_01 / ml2.c < prev    next >
Text File  |  1985-08-19  |  21KB  |  807 lines

  1. /*
  2. HEADER: CUG 121.??;
  3.  
  4.     TITLE:    ml2 - modified l2 linker;
  5.     VERSION:    1.0;
  6.     DATE:    01/11/86;
  7.     DESCRIPTION: "ML2 is a version of Scott Layson's L2 linker which has been
  8.         modified to produce MP/M modules.  The only usage change is
  9.         the addition of the -r flag which will start the specified
  10.         runtime file at the specified address, then build the rest of
  11.         the module after it.
  12.         For further information on L2, see the reference below.";
  13.     KEYWORDS:    link;
  14.     SYSTEM:    MP/M;
  15.     FILENAME:    ML2.C;
  16.     WARNINGS:    "Requires chario.c for link (this is supplied with the
  17.         distributed version of l2).
  18.         This program has not been tested by the librarian, due to
  19.         lack of the MP/M operating system.";
  20.     AUTHORS:    Scott W. Layson, Stephen M. Kenton;
  21.     COMPILERS:    BDS-C 1.50;
  22.     REFERENCES:
  23.         AUTHORS: Scott W. Layson;
  24.         TITLE:   "The Mark of the Unicorn Linker for BDS C";
  25.     ENDREF
  26. */
  27.  
  28. /* ML2.C    New linker for BDS C to produce MP/M modules
  29.  
  30.         Written 1980 by Scott W. Layson
  31.         Modified from L2.C by Stephen M. Kenton
  32.         This code is in the public domain.
  33.  
  34. This is an improved linker for BDS C CRL format.  It eliminates the
  35. jump table at the beginning of each function in the object code,
  36. thus saving up to 10% or so in code space with a slight improvement
  37. in speed.  
  38.  
  39.         [81.4.13] Switches automatically to two-pass, windowing link
  40.                      if it runs out of memory.
  41.  
  42.         [81.4.13] Symbol table is now in the order that the
  43.                      functions occur in memory; this seems more
  44.                      useful.  Also, link stats are added on the end;
  45.                      this only slightly confuses SID.
  46.  
  47.         [81.4.27] "-wa" appends link stats to the .sym file; "-ws"
  48.                      writes them to a separate file; "-w" does
  49.                      neither.  "Version 2.1" message.
  50.  
  51.         [81.4.27] Overlay capability now exists.  It works a bit
  52.                      differently from CLINK:  the option
  53.                    -ovl <base name> <origin>
  54.                      causes symbols to be read from <base name>.sym
  55.                      and produces a segment linked at <origin>.  It
  56.                      also defaults the name of the overlay function to
  57.                      that of the first .crl file (to override, put -m
  58.                      after the -ovl), and replaces c.ccc with a jump
  59.                      to that function.  Also note that the base
  60.                      symbols are loaded at the very beginning, so name
  61.                      conflicts are always resolved in favor of the
  62.                      base.
  63.  
  64.         [82.1.1] "-R"  added to relocate the run time library.
  65.             The syntax is similar to the "-ovl" option,
  66.             but the file name is the run time library.
  67.  
  68. */
  69.  
  70.  
  71. /**************** Globals ****************/
  72.  
  73. #define    OVERLAYS
  74.  
  75. #include <bdscio.h>            /* for i/o buffer defs */
  76.  
  77. #define NUL        0
  78. #define FLAG        char
  79. #define repeat     while (1)
  80.  
  81. #define STDOUT        1
  82.  
  83. /* Phase control */
  84. #define INMEM        1        /* while everything still fits */
  85. #define DISK1        2        /* overflow; finish building table */
  86. #define DISK2        3        /* use table to do window link */
  87. int phase;
  88.  
  89.  
  90. /* function table */
  91. struct funct {
  92.     char fname[9];
  93.     FLAG flinkedp;            /* in memory already? */
  94.     char *faddr;            /* address of first ref link if not linked */
  95.     } ftab [300];
  96. int nfuncts;                /* no. of functions in  table */
  97.  
  98. #define LINKED        1        /* (flinkedp) function really here */
  99. #define EXTERNAL    2        /* function defined in separate symbol table */
  100.  
  101. char fdir [512];            /* CRL file function directory */
  102.  
  103. /* command line parameters etc. */
  104. int nprogs, nlibs;
  105. char progfiles [30] [15];    /* program file names */
  106. char libfiles [20] [15];        /* library file names */
  107. FLAG symsp,                /* write symbols to .sym file? */
  108.     appstatsp,            /* append stats to .sym file? */
  109.     sepstatsp;            /* write stats to .lnk file? */
  110. char mainfunct[10];
  111. #ifdef    OVERLAYS
  112. FLAG ovlp,                /* make overlay? */
  113.     relocp;                /* or relocate root? */
  114. #endif
  115. char runfile [15];            /* run time library file name */
  116. char symsfile [15];            /* file to load symbols from (for overlays) */
  117.  
  118. /* useful things to have defined */
  119. struct inst {
  120.     char opcode;
  121.     char *address;
  122.     };
  123.  
  124. union ptr {
  125.     unsigned u;            /* an int */
  126.     unsigned *w;            /* a word ptr */
  127.     char *b;                /* a byte ptr */
  128.     struct inst *i;        /* an instruction ptr */
  129.     };
  130.  
  131.  
  132. /* Link control variables */
  133.  
  134. union ptr codend;            /* last used byte of code buffer + 1 */
  135. union ptr exts;            /* start of externals */
  136. union ptr acodend;            /* actual code-end address */
  137. unsigned extspc;            /* size of externals */
  138. unsigned origin;            /* origin of code */
  139. unsigned buforg;            /* origin of code buffer */
  140. unsigned jtsaved;            /* bytes of jump table saved */
  141.  
  142. char *lspace;                /* space to link in */
  143. char *lspcend;                /* end of link area */
  144. char *lodstart;            /* beginning of current file */
  145.  
  146.  
  147. /* i/o buffer */
  148. struct iobuf {
  149.     int fd;
  150.     int isect;            /* currently buffered sector */
  151.     int nextc;            /* index of next char in buffer */
  152.     char buff [128];
  153.     } ibuf, obuf;
  154.  
  155. /* BDS C i/o buffer */
  156. char symbuf[BUFSIZ];
  157.  
  158. /* seek opcodes */
  159. #define ABSOLUTE 0
  160. #define RELATIVE 1
  161.  
  162. #define INPUT 0
  163.  
  164. #define TRUE (-1)
  165. #define FALSE 0
  166. #define NULL 0
  167.  
  168. /* 8080 instructions */
  169. #define LHLD 0x2A
  170. #define LXIH 0x21
  171. #define SPHL 0xF9
  172. #define JMP  0xC3
  173. #define CALL 0xCD
  174.  
  175. /* strcmp7 locals, made global for speed */
  176. char _c1, _c2, _end1, _end2;
  177.  
  178. /**************** End of Globals ****************/
  179.  
  180.  
  181.  
  182. main (argc, argv)
  183.     int argc;
  184.     char **argv;
  185. {
  186.     puts ("Mark of the Unicorn Linker for BDS C, vsn. 2.1M\n");
  187.     setup (argc, argv);
  188.     linkprog();
  189.     linklibs();
  190.     if (phase == DISK1) rescan();
  191.     else wrtcom();
  192.     if (symsp) wrtsyms();
  193.     }
  194.  
  195.  
  196. setup (argc, argv)            /* initialize function table, etc. */
  197.     int argc;
  198.     char **argv;
  199. {
  200.     symsp = appstatsp = sepstatsp = FALSE;
  201.     ovlp = relocp = FALSE;
  202.     nprogs = 0;
  203.     nlibs = 0;
  204.     strcpy (&mainfunct, "MAIN");
  205.     strcpy (&runfile, "C.CCC");
  206.     origin = 0x100;
  207.     cmdline (argc, argv);
  208.     lspace = endext();
  209.     lspcend = topofmem() - 1024;
  210.     loadccc();
  211.     nfuncts = 0;
  212. #ifdef OVERLAYS
  213.     if (ovlp) loadsyms();
  214. #endif
  215.     intern (&mainfunct);
  216.     phase = INMEM;
  217.     buforg = origin;
  218.     jtsaved = 0;
  219.     }
  220.  
  221.  
  222. cmdline (argc, argv)        /* process command line */
  223.     int argc;
  224.     char **argv;
  225. {
  226.     int i, progp;
  227.  
  228.     if (argc < 1) {
  229.         puts ("Usage is:\n");
  230.         puts ("  ml2 {program files} -l {library files} [-w]\n");
  231.         exit (1);
  232.         }
  233.     progp = TRUE;
  234.     for (i=1; i < argc; ++i) {
  235.         if (argv[i][0] == '-') {
  236.             if (!strcmp (argv[i], "-L")) progp = FALSE;
  237.             else if (!strcmp (argv[i], "-W")) symsp = TRUE;
  238.             else if (!strcmp (argv[i], "-WA")) symsp = appstatsp = TRUE;
  239.             else if (!strcmp (argv[i], "-WS")) symsp = sepstatsp = TRUE;
  240.             else if (!strcmp (argv[i], "-M")) {
  241.                 if (++i >= argc) Fatal ("-m argument missing.\n");
  242.                 strcpy (&mainfunct, argv[++i]);
  243.                 }
  244. #ifdef OVERLAYS
  245.             else if (!strcmp (argv[i], "-OVL")) {
  246.                 ovlp = TRUE;
  247.                 if (i + 2 >= argc) Fatal ("-ovl argument missing.\n");
  248.                 strcpy (&symsfile, argv[++i]);
  249.                 sscanf (argv[++i], "%x", &origin);
  250.                 }
  251.             else if (!strcmp (argv[i], "-R")) {
  252.                 relocp = TRUE;
  253.                 if (i + 2 >= argc) Fatal ("-r argument missing");
  254.                 strcpy (&runfile, argv[++i]);
  255.                 sscanf (argv[++i], "%x", &origin);
  256.                 }
  257. #endif
  258.             else printf ("Unknown option: '%s'\n", argv[i]);
  259.             }
  260.         else {
  261.             if (progp) strcpy (&progfiles[nprogs++], argv[i]);
  262.             else strcpy (&libfiles[nlibs++], argv[i]);
  263.             }
  264.         }
  265.     if (ovlp) strcpy (&mainfunct, &progfiles[0]);
  266.     strcpy(&libfiles[nlibs++], "LOCAL.CRL") ;
  267.     strcpy(&libfiles[nlibs++], "DEFF.CRL") ;
  268.     strcpy(&libfiles[nlibs++], "DEFF2.CLR") ;
  269.     }
  270.  
  271.  
  272. loadccc()                    /* load C.CCC (runtime library) */
  273. {
  274.     union ptr temp;
  275.     unsigned len;
  276.  
  277.     codend.b = lspace;
  278.     if (!ovlp) {
  279.         if (copen (&ibuf, runfile) < 0)
  280.             Fatal ("Can't open C.CCC\n");
  281.         if (cread (&ibuf, lspace, 128) < 128)    /* read a sector */
  282.             Fatal ("C.CCC: read error!\n");
  283.         temp.b = lspace + 0x17;
  284.         len = *temp.w;                        /* how long is it? */
  285.         cread (&ibuf, lspace + 128, len - 128);    /* read rest */
  286.         codend.b += len;
  287.         cclose (&ibuf);
  288.         }
  289.     else